// SocketConnection.cpp: implementation of the CSocketConnection class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SocketConnection.h"
#include "ftp_exception.h"
#include <winsock2.h>
#include <ws2tcpip.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSocketConnection::CSocketConnection()
{
	m_socket = NULL;
}

CSocketConnection::~CSocketConnection()
{
	if(m_socket != NULL)
		closesocket(m_socket);
}

void CSocketConnection::Connect(const char* ip, const char* port)
{
	//Get address info
	//struct addrinfo aiHints;
	struct addrinfo *aiList = NULL;

	//aiHints.ai_family = AF_INET;
	//aiHints.ai_socktype = SOCK_STREAM;
	//aiHints.ai_protocol = IPPROTO_TCP;

	int retVal = getaddrinfo(ip, port, NULL, &aiList);

	if(retVal != 0)
	{
		if(aiList != NULL)
			freeaddrinfo(aiList);

		int error = WSAGetLastError();

		throw socket_exception("");
	}

	//Create socket
	struct addrinfo* pinfo = aiList;
	m_socket = socket(pinfo->ai_family, pinfo->ai_socktype, pinfo->ai_protocol);

	if(m_socket == INVALID_SOCKET)
	{
		freeaddrinfo(aiList);
		throw socket_exception("create socket failed");
	}


	//Connect
	retVal = ::connect(m_socket, aiList->ai_addr, (int)aiList->ai_addrlen);
	freeaddrinfo(aiList);

	if(retVal == SOCKET_ERROR)
	{
		throw socket_exception("Connection failed");
	}

}

void CSocketConnection::SetSocketOpt(int level, int optname, const char* optval, int optlen)
{
	setsockopt(m_socket, level, optname, optval, optlen);
}

void CSocketConnection::Send(const char *buf, int len)
{
	::send(m_socket, buf, len, 0);
}



int CSocketConnection::Receive(char *buf, int len)
{
	return ::recv(m_socket, buf, len, 0);
}

int CSocketConnection::Receive(char* buf, int len, int timeout)
{
	timeval time;
	time.tv_sec = timeout;
	time.tv_usec = 0;

	fd_set set;
	FD_ZERO(&set);
	FD_SET(m_socket, &set);

	int ret = select(0, &set, NULL, NULL, &time);

	if(ret != 0)
	{
		return ::recv(m_socket, buf, len, 0);
	}
	else
	{
		return 0;
	}
}